package watchtcp

import (
	globaldata "earth/global_data"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
)

type CommandPayload struct {
	Method string                 `json:"method"`
	Params map[string]interface{} `json:"params"`
}

// topic:devices/command/{mac}/{message_id}
func DealTpCommand(topic string, payload []byte) error {
	// 校验主题合法性获取mac地址
	deviceNumber, err := getDeviceNumberFromTopic(topic)
	if err != nil {
		return err
	}
	logrus.Info("deviceNumber:", deviceNumber)

	// 解析payload
	p, err := ParseCommandPayload(payload)
	if err != nil {
		return err
	}
	// 发送命令给设备
	err = AssembleCommandPayload(deviceNumber, p.Method, p.Params)
	return err
}

// 从主题中解析出mac地址
func getDeviceNumberFromTopic(topic string) (string, error) {
	topicList := strings.Split(topic, "/")
	if len(topicList) < 5 {
		return "", fmt.Errorf("topic:%s is invalid", topic)
	}
	// 验证devices/command/开头
	if topicList[2] != "devices" || topicList[3] != "command" {
		return "", fmt.Errorf("topic:%s is invalid", topic)
	}
	// MAC地址
	return topicList[4], nil
}

// 解析payload
func ParseCommandPayload(payload []byte) (*CommandPayload, error) {
	// payload转json
	var commandPayload CommandPayload
	err := json.Unmarshal(payload, &commandPayload)
	if err != nil {
		return nil, err
	}
	// logrus.Info("commandPayload:", commandPayload)
	return &commandPayload, nil
}

func AssembleCommandPayload(deviceNumber, method string, params map[string]interface{}) error {
	// 组装命令
	// logrus.Info("deviceNumber:", deviceNumber)
	// logrus.Info("method:", method)
	// logrus.Info("params:", params)
	// 注意，这里deviceNumber是deviceID,根据deviceID找到对应的设备，然后发送命令给设备
	// 在老的版本这里的deviceNumber是IMEI（accesstoken)
	if viper.GetString("version") == "old" {
		// 根据IMEI找到对应的设备id
		deviceNumber = globaldata.IMEIToDeviceIDMap[deviceNumber]
	}
	value, ok := globaldata.GetConnByDeviceID(deviceNumber)
	if !ok {
		return fmt.Errorf("deviceNumber:%s is not connected", deviceNumber)
	}
	// value转为*WatchTcp
	w, ok := value.(*WatchTcp)
	if !ok {
		return fmt.Errorf("deviceNumber:%s is not connected", deviceNumber)
	}
	if w.PsiFunction == nil {
		logrus.Warn("PsiFunction is nil")
		return fmt.Errorf("deviceNumber:%s PsiFunction is nil", deviceNumber)
	}
	var messageContent string
	// 从映射表中取出对应的处理函数
	if dealFunc, ok := w.PsiFunction.DealFuncs[method]; ok {
		m, err := dealFunc(method, params)
		if err != nil {
			return err
		}
		messageContent = m
	} else {
		logrus.Error("Other message:" + method)
		return nil
	}
	// 组装
	message := w.GenerateCommandMessage(method, messageContent)
	// 回复消息
	w.Mutex.Lock()
	defer w.Mutex.Unlock()
	_, err := w.Conn.Write([]byte(message))
	if err != nil {
		logrus.Error("Error writing:", err.Error())
	}
	logrus.Debug("\ni====>device:", message)
	return nil
}

// 生成指令消息
func (w *WatchTcp) GenerateCommandMessage(method string, messageContent string) string {
	// DW*334588000000156*0002*CR
	message := fmt.Sprintf("%s*%s*%04X*%s\n", w.Manufacturer, w.IMEI, len(messageContent), messageContent)
	return message
}
